#include "./stl_util_test.h"

TEST(Dictionary, constructor_void) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();

	// Assert
	EXPECT_TRUE( dict1 != NULL );

};

TEST(Dictionary, constructor_copy) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();
	dict1->insert( make_pair( "label", 2 ) );
	Dictionary<int> *dict2 = new Dictionary<int>( *dict1 );

	// Assert
	EXPECT_TRUE( dict1 != NULL );
	EXPECT_TRUE( dict2 != NULL );
	EXPECT_EQ( *dict1, *dict2 );

};

TEST(Dictionary, at_throws_InvalidEntryException) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();
	bool right_exception = false;

	// Act
	try {
		dict1->at(string("0"));
	}
	catch ( InvalidEntryException ){
		right_exception = true;
	}
	catch ( ... ){
		right_exception = false;
	}

	// Assert
	EXPECT_TRUE( right_exception );

};

TEST(Dictionary, insert_pairStringAndInt) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();

	// Act
	dict1->insert( make_pair("label", 1) );

	// Assert
	EXPECT_EQ( dict1->at("label"), 1 );

};

TEST(Dictionary, insert_string_int) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();

	// Act
	dict1->insert( "label", 1 );

	// Assert
	EXPECT_EQ( dict1->at("label"), 1 );

};

TEST(Dictionary, size) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();

	// Act
	// Assert
	EXPECT_EQ( dict1->size(), 0 );
	dict1->insert( make_pair("label", 1) );
	EXPECT_EQ( dict1->size(), 1 );
	dict1->insert( make_pair("label", 2) ); // same label
	EXPECT_EQ( dict1->size(), 1 ); // no change
	dict1->insert( make_pair("labelB", 1) );
	EXPECT_EQ( dict1->size(), 2 );

};

// REMEMBER - char[] + int cannot be overriden and doesn't make what I want
TEST(Dictionary, operatorComma) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();

	// Act
	(*dict1), make_pair("label0", 0), make_pair("label1", 1), make_pair("label2", 2), make_pair("label3", 3);

	// Assert
	string label = "";
	for( usint i = 0; i < 4; ++i )
		EXPECT_EQ( dict1->at( "label" + itos(i) ), (int) i );

};

TEST(Dictionary, operatorBrackets_string) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();

	// Act
	dict1->insert( make_pair("label", 1) );

	// Assert
	EXPECT_EQ( (*dict1)["label"], 1 );

	// Act
	(*dict1)["label"] = -1;

	// Assert
	EXPECT_EQ( (*dict1)["label"], -1 );

};

TEST(Dictionary, operatorEqual_DictionaryInt_and_DictionaryInt_true) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();
	Dictionary<int> *dict2 = new Dictionary<int>();

	// Act
	(*dict1), make_pair("label1", 1), make_pair("label2", 2), make_pair("label3", 3);
	(*dict2), make_pair("label1", 1), make_pair("label2", 2), make_pair("label3", 3);

	// Assert
	EXPECT_TRUE( (*dict1) == (*dict2) );

};

TEST(Dictionary, operatorEqual_DictionaryInt_and_DictionaryInt_false_size) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();
	Dictionary<int> *dict2 = new Dictionary<int>();

	// Act
	(*dict1), make_pair("label1", 1), make_pair("label2", 2), make_pair("label3", 3);
	(*dict2), make_pair("label1", 1), make_pair("label2", 2);

	// Assert
	EXPECT_FALSE( (*dict1) == (*dict2) );

};

TEST(Dictionary, operatorEqual_DictionaryInt_and_DictionaryInt_false_content) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();
	Dictionary<int> *dict2 = new Dictionary<int>();

	// Act
	(*dict1), make_pair("label1", 1), make_pair("label2", 2), make_pair("label3", 3);
	(*dict2), make_pair("label1", 1), make_pair("label2", 2), make_pair("label3", 4);

	// Assert
	EXPECT_FALSE( (*dict1) == (*dict2) ) << endl << (*dict1) << " and " << (*dict2) << endl;

};

TEST(Dictionary, operatorNotEqual_DictionaryInt_and_DictionaryInt_false) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();
	Dictionary<int> *dict2 = new Dictionary<int>();

	// Act
	(*dict1), make_pair("label1", 1), make_pair("label2", 2), make_pair("label3", 3);
	(*dict2), make_pair("label1", 1), make_pair("label2", 2), make_pair("label3", 3);

	// Assert
	EXPECT_FALSE( (*dict1) != (*dict2) );

};

TEST(Dictionary, operatorNotEqual_DictionaryInt_and_DictionaryInt_true_size) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();
	Dictionary<int> *dict2 = new Dictionary<int>();

	// Act
	(*dict1), make_pair("label1", 1), make_pair("label2", 2), make_pair("label3", 3);
	(*dict2), make_pair("label1", 1), make_pair("label2", 2);

	// Assert
	EXPECT_TRUE( (*dict1) != (*dict2) );

};

TEST(Dictionary, operatorNotEqual_true_DictionaryInt_and_DictionaryInt_content) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();
	Dictionary<int> *dict2 = new Dictionary<int>();

	// Act
	(*dict1), make_pair("label1", 1), make_pair("label2", 2), make_pair("label3", 3);
	(*dict2), make_pair("label1", 1), make_pair("label2", 2), make_pair("label3", 4);

	// Assert
	EXPECT_TRUE( (*dict1) != (*dict2) ) << endl << (*dict1) << " and " << (*dict2) << endl;

};

// having an operator == defined I can use EXPECT_EQ
TEST(Dictionary, DictionaryInt_iterator) {

	// Arrange
	Dictionary<int> *dict1 = new Dictionary<int>();
	Dictionary<int> *dict2 = new Dictionary<int>();

	// Act
	(*dict1), make_pair("label1", 1), make_pair("label2", 2), make_pair("label3", 3);
	(*dict2), make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6);

	for( Dictionary<int>::Iter i = dict1->begin(); i != dict1->end(); ++i )
		i->second *= 2;

	// Assert
	EXPECT_EQ( (*dict1)["label1"], (*dict2)["label1"] );
	EXPECT_EQ( (*dict1), (*dict2) );

};

TEST(Dictionary, operatorAttribution_DictionaryInt_and_DictionaryInt) {

	// Arrange
	Dictionary<int> dict1, final_dict1;
	dict1, make_pair("label1", 1), make_pair("label2", 2), make_pair("label3", 3);
	final_dict1, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6);

	Dictionary<int> dict2, final_dict2;
	dict2, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6);
	final_dict2.copy( dict2 );

	Dictionary<int> expected;
	expected, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6);

	// Act
	Dictionary<int> actual = ( dict1 = dict2 );

	// Assert
	EXPECT_EQ( dict1, final_dict1 ) << "Dict1 " << dict1 << " | FDict1 " << final_dict1 << pendl;
	EXPECT_EQ( dict2, final_dict2 ) << "Dict2 " << dict2 << " | FDict2 " << final_dict2 << pendl;
	EXPECT_EQ( expected, actual );
};

TEST(Dictionary, operatorAddition_DictionaryInt_and_DictionaryInt) {

	// Arrange
	Dictionary<int> dict1, final_dict1;
	dict1, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6);
	final_dict1.copy( dict1 );

	Dictionary<int> dict2, final_dict2;
	dict2, make_pair("label2", -2), make_pair("label3", -4), make_pair("label4", -6);
	final_dict2.copy( dict2 );

	Dictionary<int> expected;
	expected, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6), make_pair("label4", -6);

	// Act
	Dictionary<int> actual = dict1 + dict2;

	// Assert
	EXPECT_EQ( dict1, final_dict1 ) << "Dict1 " << dict1 << " | FDict1 " << final_dict1 << pendl;
	EXPECT_EQ( dict2, final_dict2 ) << "Dict2 " << dict2 << " | FDict2 " << final_dict2 << pendl;
	EXPECT_EQ( expected, actual );

};

TEST(Dictionary, operatorAdditionAndAttribution_DictionaryInt_and_DictionaryInt) {

	// Arrange
	Dictionary<int> dict1, final_dict1;
	dict1, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6);
	final_dict1, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6), make_pair("label4", -6), make_pair("label5", 0);

	Dictionary<int> dict2, final_dict2;
	dict2, make_pair("label2", -2), make_pair("label3", -4), make_pair("label4", -6);
	final_dict2.copy( dict2 );

	Dictionary<int> dict3, final_dict3;
	dict3, make_pair("label3", 0), make_pair("label5", 0);
	final_dict3.copy( dict3 );

	Dictionary<int> expected;
	expected, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6), make_pair("label4", -6), make_pair("label5", 0);

	// Act
	Dictionary<int> actual = ( ( dict1 += dict2 ) += dict3 );

	// Assert
	EXPECT_EQ( dict1, final_dict1 ) << "Dict1 " << dict1 << " | FDict1 " << final_dict1 << pendl;
	EXPECT_EQ( dict2, final_dict2 ) << "Dict2 " << dict2 << " | FDict2 " << final_dict2 << pendl;
	EXPECT_EQ( dict3, final_dict3 ) << "Dict3 " << dict3 << " | FDict3 " << final_dict3 << pendl;
	EXPECT_EQ( expected, actual ) << "expected " << expected << " | actual " << actual << pendl;

};

TEST(Dictionary, toS) {

	// Arrange
	Dictionary<int> dict1, final_dict1;
	dict1, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6);
	final_dict1.copy( dict1 );

	string expected = "[ { label1, 2 } { label2, 4 } { label3, 6 } ]";

	// Act
	string actual = dict1.toS();

	// Assert
	EXPECT_EQ( dict1, final_dict1 ) << "Dict1 " << dict1 << " | FDict1 " << final_dict1 << pendl;
	EXPECT_EQ( expected, actual );

};

TEST(Dictionary, operatorAddition_DictionaryInt_and_string) {

	// Arrange
	Dictionary<int> dict1, final_dict1;
	dict1, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6);
	final_dict1.copy( dict1 );

	string str1 = " dict", final_str1 = " dict";

	string expected = "[ { label1, 2 } { label2, 4 } { label3, 6 } ] dict";

	// Act
	string actual = dict1 + str1;

	// Assert
	EXPECT_EQ( dict1, final_dict1 ) << "Dict1 " << dict1 << " | FDict1 " << final_dict1 << pendl;
	EXPECT_EQ( expected, actual );

};

TEST(Dictionary, operatorAddition_string_and_DictionaryInt) {

	// Arrange
	Dictionary<int> dict1, final_dict1;
	dict1, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6);
	final_dict1.copy( dict1 );

	string str1 = "dict ", final_str1 = "dict ";

	string expected = "dict [ { label1, 2 } { label2, 4 } { label3, 6 } ]";

	// Act
	string actual = str1 + dict1;

	// Assert
	EXPECT_EQ( dict1, final_dict1 ) << "Dict1 " << dict1 << " | FDict1 " << final_dict1 << pendl;
	EXPECT_EQ( expected, actual );

};

TEST(Dictionary, operatorAdditionAndAttribution_string_and_DictionaryInt) {

	// Arrange
	Dictionary<int> dict1, final_dict1;
	dict1, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6);
	final_dict1.copy( dict1 );

	string str1 = "dict ", final_str1 = "dict [ { label1, 2 } { label2, 4 } { label3, 6 } ]";

	string expected = "dict [ { label1, 2 } { label2, 4 } { label3, 6 } ]";

	// Act
	string actual = ( str1 += dict1 );

	// Assert
	EXPECT_EQ( dict1, final_dict1 ) << "Dict1 " << dict1 << " | FDict1 " << final_dict1 << pendl;
	EXPECT_EQ( expected, actual );

};

TEST(Dictionary, operatorAddition_DictionaryInt_and_charPtr) {

	// Arrange
	Dictionary<int> dict1, final_dict1;
	dict1, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6);
	final_dict1.copy( dict1 );

	string expected = "[ { label1, 2 } { label2, 4 } { label3, 6 } ] dict";

	// Act
	string actual = dict1 + " dict";

	// Assert
	EXPECT_EQ( dict1, final_dict1 ) << "Dict1 " << dict1 << " | FDict1 " << final_dict1 << pendl;
	EXPECT_EQ( expected, actual );

};

TEST(Dictionary, operatorAddition_charPtr_and_DictionaryInt) {

	// Arrange
	Dictionary<int> dict1, final_dict1;
	dict1, make_pair("label1", 2), make_pair("label2", 4), make_pair("label3", 6);
	final_dict1.copy( dict1 );

	string expected = "dict [ { label1, 2 } { label2, 4 } { label3, 6 } ]";

	// Act
	string actual = "dict " + dict1;

	// Assert
	EXPECT_EQ( dict1, final_dict1 ) << "Dict1 " << dict1 << " | FDict1 " << final_dict1 << pendl;
	EXPECT_EQ( expected, actual );

};

// Remember ctrl+shift+insert = change ctrl+v to previous results
